#include "preHeader.h"
#include "Team.h"
#include "Session/MapServerMgr.h"

Team::Team(uint32 teamId)
: m_teamId(teamId)
, m_teamLeader(NULL)
{
}

Team::~Team()
{
	for (auto& pair : m_teamMemebers) {
		pair.second->pTeam = NULL;
	}
}

void Team::AddMember(Character* pChar)
{
	m_teamMemebers[pChar->guid] = pChar;
	pChar->pTeam = this;
	if (m_teamLeader == NULL) {
		m_teamLeader = pChar;
	}

	SendTeamInfoToAllMembers();
	SendTeamInfoToAllMemberInstances();

	NetPacket pack2C(SMSG_TEAM_MEMBER_ADD);
	pack2C << pChar->guid << pChar->name;
	SendPacketToAllMembers(pack2C);

	NetPacket pack2I(G2M_TEAM_MEMBER_ADD);
	pack2I << m_teamId << pChar->guid;
	SendPacketToAllMemberInstances(pack2I);
}

void Team::RemoveMemeber(Character* pChar, Character* pKicker)
{
	m_teamMemebers.erase(pChar->guid);
	pChar->pTeam = NULL;
	if (m_teamLeader == pChar) {
		auto pPriorMember = GetPriorMember();
		if (pPriorMember != NULL) {
			ChangeLeader(pPriorMember);
		}
	}

	NetPacket pack2C(SMSG_TEAM_MEMBER_QUIT);
	pack2C << pChar->guid << pChar->name;
	if (pKicker != NULL) {
		pack2C << pKicker->guid << pKicker->name;
	}
	SendPacketToAllMembers(pack2C);

	NetPacket pack2I(G2M_TEAM_MEMBER_QUIT);
	pack2I << pChar->guid;
	SendPacketToAllMemberInstances(pack2I);

	SendTeamInfoToAllMembers();
	SendTeamInfoToAllMemberInstances();
}

void Team::ChangeLeader(Character* pChar)
{
	m_teamLeader = pChar;

	NetPacket pack2C(SMSG_TEAM_LEADER_CHANGE);
	pack2C << pChar->guid << pChar->name;
	SendPacketToAllMembers(pack2C);

	NetPacket pack2I(G2M_TEAM_LEADER_CHANGE);
	pack2I << m_teamId << pChar->guid << pChar->name;
	SendPacketToAllMemberInstances(pack2I);
}

void Team::SendTeamSyncInfoToAllMembers() const
{
	NetPacket pack(SMSG_TEAM_SYNC_INFO);
	PackTeamSyncInfo4Member(pack);
	SendPacketToAllMembers(pack);
}

void Team::SendTeamInfoToAllMembers() const
{
	NetPacket pack(SMSG_TEAM_INFO);
	PackTeamInfo4Member(pack);
	SendPacketToAllMembers(pack);
}

void Team::SendTeamInfoToAllMemberInstances() const
{
	NetPacket pack(G2M_TEAM_INFO);
	PackTeamInfo4Instance(pack);
	SendPacketToAllMemberInstances(pack);
}

void Team::SendTeamInfoToInstance(InstGUID instGuid) const
{
	NetPacket pack(G2M_TEAM_INFO);
	PackTeamInfo4Instance(pack);
	sMapServerMgr.RouteToInstance(instGuid, pack);
}

void Team::SendPacketToAllMembers(const INetPacket& pck) const
{
	for (auto& pair : m_teamMemebers) {
		pair.second->SendPacket(pck);
	}
}

void Team::SendPacketToAllMemberInstances(const INetPacket& pck) const
{
	size_t n = 0;
	InstGUID instGuids[MAX_TEAM_MEMBER];
	for (auto& pair : m_teamMemebers) {
		auto instGuid = pair.second->lastInstGuid;
		if (!IS_INPTR_CONTAIN_VALUE(instGuids, n, instGuid)) {
			sMapServerMgr.RouteToInstance(instGuid, pck);
			instGuids[n++] = instGuid;
		}
	}
}

void Team::PackTeamSyncInfo4Member(INetPacket& pck) const
{
	pck << (u16)m_teamMemebers.size();
	for (auto& pair : m_teamMemebers) {
		auto pChar = pair.second;
		pck << pChar->guid
			<< pChar->lastLevel << pChar->lastPercHP
			<< pChar->lastInstGuid;
	}
}

void Team::PackTeamInfo4Member(INetPacket& pck) const
{
	pck << m_teamId << m_teamLeader->guid;
	pck << (u16)m_teamMemebers.size();
	for (auto& pair : m_teamMemebers) {
		auto pChar = pair.second;
		pck << pChar->guid << pChar->name << pChar->career
			<< pChar->lastLevel << pChar->lastPercHP
			<< pChar->lastInstGuid;
	}
}

void Team::PackTeamInfo4Instance(INetPacket& pck) const
{
	pck << m_teamId
		<< m_teamLeader->guid << m_teamLeader->name;
	pck << (u16)m_teamMemebers.size();
	for (auto& pair : m_teamMemebers) {
		pck << pair.first;
	}
}

bool Team::HasTeamMemberOnline() const
{
	for (auto& pair : m_teamMemebers) {
		if (pair.second->isOnline) {
			return true;
		}
	}
	return false;
}

Character* Team::GetPriorMember() const
{
	Character* pSltChar = NULL;
	for (auto& pair : m_teamMemebers) {
		auto pChar = pair.second;
		if (pSltChar == NULL ||
			pSltChar->lastLevel < pChar->lastLevel) {
			pSltChar = pChar;
		}
	}
	return pSltChar;
}
